# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import pymysql,requests,time

from email.header import Header
from email.mime.text import MIMEText
from email.utils import parseaddr, formataddr
import smtplib
import re
import base64
import logging,redis
from pprint import pformat
from decimal import Decimal



logger = logging.getLogger('weblog')
logger.setLevel(logging.DEBUG)
fh = logging.FileHandler('weblog.log')
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(process)d - %(levelname)s - %(message)s')
fh.setFormatter(formatter)
ch.setFormatter(formatter)
logger.addHandler(fh)
logger.addHandler(ch)



def _format_addr(s):
    name, addr = parseaddr(s)
    return formataddr(( \
        Header(name, 'utf-8').encode(), \
        addr.encode('utf-8') if isinstance(addr, unicode) else addr))



def send_email(addr,title,text):
    from_addr = '*******'
    password = '******'
    to_addr = addr
    smtp_server = 'smtp.163.com'
    msg = MIMEText(text, 'plain', 'utf-8')
    msg['From'] = _format_addr('姚航 <%s>' % from_addr)
    msg['To'] = _format_addr('陈吉全 <%s>' % to_addr)
    msg['Subject'] = Header(title, 'utf-8').encode()
    server = smtplib.SMTP(smtp_server,25,timeout=10)
    server.set_debuglevel(0)
    server.login(from_addr, password)
    server.sendmail(from_addr, [to_addr], msg.as_string())
    server.quit()


URL_MAIN = 'http://shop.10086.cn/i/?f=rechargecredit'
URL_TMP_NUMAREA = 'http://shop.10086.cn/i/v1/res/numarea/%s'
URL_TMP_PAYRULE = 'http://shop.10086.cn/i/v1/pay/payrule/%s'
URL_TMP_ORDER = 'http://shop.10086.cn/i/v1/pay/saveorder/%s'





class APIError(RuntimeError):
	def __init__(self, errno, msg):
		self.errno = errno
		self.msg = msg

class ClientError(RuntimeError):
	def __init__(self, msg):
		self.msg = msg

class APIClient(object):

	def __init__(self):  
		self.session = requests.Session()  


	def get_ip(self):
		return requests.get('http://s.zdaye.com/?api=201611160829244358&count=1&fitter=2&px=2').text  #代理ip地址

	def get_num_area(self, phone):  #获取号码归属地
		url = URL_TMP_NUMAREA % phone 
		rep = self.session.get(url,timeout = 60)  
		return self.get_data(rep)  

	def get_pay_rule(self, phone, prov):  #获取支付规则
		url = URL_TMP_PAYRULE % phone  
		d = {'amountFlag': 1, 'saleFlag': 1, 'enableFlag': 1, 'enableType': 0, 'saleQueryType': 2,
			 'phoneNo': base64.b64encode(phone), 'provCode': prov, 'channel': '00'} 
		rep = self.session.post(url, json=d,timeout = 10) 
		return self.get_data(rep)  

	def get_order(self, phone, pay_rule, amount):  #提交订单
		url = URL_TMP_ORDER % phone  
		sale_code = pay_rule['saleCode']  
		amount = Decimal(str(amount))
		money = dict(charge=amount, choose=amount, actual=amount)
		if re.match(r'\d+\.\d+', sale_code):
			rate = Decimal(sale_code)
			money['actual'] = amount * rate
		elif re.match(r'\d+~\d+:\d+', sale_code):
			# 100~100:1,200~200:2,300~300:3,500~500:5
			items = sale_code.split(',')
			for item in items:
				m = re.match(r'(\d+)~(\d+):(\d+)', item)
				if m:
					a, b, c = map(int, m.groups())
					if a <= amount <= b:
						money['charge'] = amount + c
						break
		else:
			errmsg = '不支持的优惠策略：%s' % sale_code
			logger.error(errmsg)
			raise ClientError(errmsg)

		d = {'channel': '00', 'activityNO': '', 'operateId': pay_rule['operateId'],
			 'amount': money['actual'], 'chargeMoney': money['charge'], 'choseMoney': money['choose'],
			 'homeProv': pay_rule['provCode']}

		logger.info('缴费金额:%.2f元', money['actual'])
		for k, v in d.iteritems():
			if isinstance(v, Decimal):
				s = str(v)
				if '.' in s:
					v = float(v)
				else:
					v = int(v)
				d[k] = v

		rep = self.session.post(url, json=d, timeout = 10)
		return self.get_data(rep)

	def get_pay_url(self, phone, amount):

		logger.info('充值手机:%s', phone)
		logger.info('充值金额:%s', amount)
		prov = self.get_num_area(phone)['prov_cd'] #获取地区代码
		logger.info('地区编码:%s', prov)
		pay_rule = self.get_pay_rule(phone, prov) #获取优惠规则
		rule_idx = 0
		rule = pay_rule['saleRules'][rule_idx]  #1111
		logger.info('套餐名称:%s', rule['saleName'])
		logger.info('套餐描述:%s', rule['saleDesc'])
		# get order
		order = self.get_order(phone, rule, amount)
		if order:
			return order['payUrl']

	def get_data(self, rep):  
		js = rep.json() 
		if js:
			errno = js.get('retCode')  
			msg = js.get('retMsg')  
			if errno != '000000':  
				raise APIError(errno, msg)  
			else:
				result = js['data']  
				return result




def dget(d, path, default=None, separator='/'):
	if isinstance(path, basestring):
		keys = path.split(separator)
	else:  
		keys = path
	for key in keys:
		d = d.get(key)
		if d is None:
			break
	if d is None:
		d = default
	return d


def web_recharg(alipay_account,alipay_password):


    driver = webdriver.Firefox()
    logger.info('已成功启动，正在等待新任务....%s'%alipay_account)

    while True:
        rcon = redis.StrictRedis(host='localhost')
        task = rcon.blpop('yaohang')
        info = eval(task[1])


        try:
            logger.info('成功获取到新任务：%s' % info)
            cli = APIClient()
            pay_url = cli.get_pay_url(str(info['phone_number']), info['money'])
            logger.info(pay_url)
        except APIError as e:
            logger.error('错误代码%s：%s' % (e.errno, e.msg))
            sql = '''INSERT INTO Recharge_record(order_id,phone_number,money,result,mobile_order_id,paid,account,date) VALUES (%s,%d,%d,'%s',%d,%s,'%s',now())''' % (
                info['ID'], info['phone_number'], info['money'], 'failure', 0, 0, alipay_account)

            try:
                db = pymysql.connect('localhost', 'root', 'qweasdzxc', 'test', charset='utf8')
                cursor = db.cursor()
                cursor.execute(sql)
                db.commit()
            except:
                db.rollback()
                logger.warning(u"订单数据写入失败---%s" % info)
            db.close()


        except ClientError as e:
            logger.error('程序错误：%s' % e.msg)

        except Exception as e:
            logger.warning('IP已被屏蔽，需要切换IP，任务已重新加入队列')
            logger.warning('%s'%e)
            rcon.lpush('yaohang',info)

        else:
            driver.get(pay_url)
            logger.debug('等待加载选择支付方式页面')
            WebDriverWait(driver, 15).until(EC.element_to_be_clickable((By.XPATH, '//*[@id="payment"]/div/ul/li[4]/label/img')))
            logger.debug('成功加载选择支付方式页面')

            driver.find_element_by_xpath('//*[@id="payment"]/div/ul/li[4]/label/img').click()
            logger.debug('点击选择支付宝')
            moile_id = int(str(driver.find_element_by_xpath('/html/body/div[2]/div[1]/div[1]/p[1]/span[4]').text).replace('订单号：',''))
            paid = float(str(driver.find_element_by_xpath('/html/body/div[2]/div[1]/div[1]/p[1]/span[5]').text).replace('￥', ''))
            phone_number = int(driver.find_element_by_xpath('/html/body/div[2]/div[1]/div[1]/p[2]/span').text)
            choose_pay = driver.current_window_handle
            time.sleep(0.5)
            driver.find_element_by_xpath('//*[@id="payment"]/div/p/input').click()
            logger.debug('点击确认支付')

            alipay = driver.current_window_handle

            for i in driver.window_handles:  #切换窗口
                if alipay == i:
                    continue
                else:
                    driver.switch_to_window(i)
            logger.debug('等待支付宝加载')

            WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, '//*[@id="J_tip_qr"]/a')))
            driver.find_element_by_xpath('//*[@id="J_tip_qr"]/a').click() #切换登录
            logger.debug('点击切换支付方式')

            logger.debug('等待加载输入框')

            try:
                WebDriverWait(driver, 5).until(EC.visibility_of_element_located((By.XPATH, '//*[@id="J_tLoginId"]')))
            except:
                driver.find_element_by_xpath('//*[@id="J_tip_qr"]/a').click()  # 切换登录
                time.sleep(0.5)

            driver.find_element_by_xpath('//*[@id="J_tLoginId"]').send_keys(alipay_account) #输入支付账号
            logger.debug('成功输入支付宝账号')
            driver.find_element_by_id('payPasswd_input').send_keys(alipay_password) #输入支付密码
            logger.debug('成功输入密码')
            time.sleep(1)

            try:
                driver.find_element_by_class_name('checkCodeImg')
                logger.warning('出现支付宝验证码')
                captcha = input('请输入页面上出现的验证码：')
                driver.find_element_by_class_name('ui-input ui-input-checkcode').send_keys(captcha)
            except:
                pass

            WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, '//*[@id="J_newBtn"]')))
            driver.find_element_by_xpath('//*[@id="J_newBtn"]').click()
            logger.debug('点击确认支付')


            try:
                WebDriverWait(driver, 5).until(EC.visibility_of_element_located((By.ID, 'payPassword_rsainput')))
            except:
                driver.find_element_by_xpath('//*[@id="J_newBtn"]').click()

            WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.ID, 'payPassword_rsainput')))
            balance = float(str(driver.find_element_by_xpath('//*[@id="J_SavecardList"]/li/div[1]/label/span[2]/em').text).replace(' 元',''))
            print balance

            if balance <= 3000:
                send_email('13666209137@139.com','账号：%s余额不足3000，目前余额：%s，请尽快充值。'%(alipay_account,balance),'账号：%s余额不足3000，目前余额：%s，请尽快充值。'%(alipay_account,balance))
                logger.warning('账号：%s余额不足3000，请尽快充值。'%alipay_account)

            driver.find_element_by_id('payPassword_rsainput').send_keys(alipay_password) #输入密码
            logger.debug('成功输入支付密码')
            time.sleep(0.5)
            driver.find_element_by_xpath('//*[@id="J_authSubmit"]').click()  #确认支付
            logger.debug('成功点击确认支付')



            WebDriverWait(driver, 30).until(EC.visibility_of_element_located((By.XPATH, '//*[@id="main"]/div/div[1]/h3')))

            if '成功' in str(driver.find_element_by_xpath('//*[@id="main"]/div/div[1]/h3').text):
                logger.info('成功充值:%s,金额:%s' %(phone_number,paid))
                driver.close()
                driver.switch_to_window(choose_pay)
                driver.find_element_by_xpath('//*[@id="popPay"]/div[2]/p[2]/a[1]').click()


                sql = '''INSERT INTO Recharge_record(order_id,phone_number,money,result,mobile_order_id,paid,account,date) VALUES (%s,%s,%s,'%s',%d,%s,'%s',now())''' % (info['ID'], phone_number, info['money'], 'success', moile_id, paid, alipay_account)
                try:
                    db = pymysql.connect('localhost', 'root', 'qweasdzxc', 'test', charset='utf8')
                    cursor = db.cursor()
                    cursor.execute(sql)
                    db.commit()
                except:
                    db.rollback()
                    logger.warning(u"订单数据写入失败---%s,%s" %(phone_number,paid))
                db.close()


if __name__ == '__main__':


    try:
        alipay_account = '******'
        alipay_password = '*****'
        web_recharg(alipay_account, alipay_password)
    except Exception as e:
        logger.error(e)
        send_email('595742100@qq.com','网页充值因意外而停止','网页充值因意外而停止')
